﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;


namespace AudioStudio
{
    public class AkGameObjPositionData
    {
        public Vector3 position;
        public Vector3 forward;
        public Vector3 up;
    }

    /// <summary>
    /// 音效物件，上层逻辑不可直接使用，需根据需求继承使用
    /// </summary>
    public class AudioGameObject : MonoBehaviour
    {
        /// Maintains and persists the Static setting of the gameobject, which is available only in the editor.
        public bool IsUpdatePosition = true;
        public bool StopOnDestroy = true;
        private AkGameObjPositionData m_posData = null;

        public bool isEnvironmentAware = true;
        private AkGameObjEnvironmentData m_envData = null;

        private Collider m_Collider;

        public void Awake()
        {
            m_Collider = GetComponent<Collider>();

            if (IsUpdatePosition)
            {
                m_posData = new AkGameObjPositionData();

                //Register a Game Object in the sound engine, with its name.
                AKRESULT res = AkSoundEngine.RegisterGameObj(Player, Player.name);
                if (res == AKRESULT.AK_Success)
                {
                    // Get position with offset
                    Vector3 position = GetPosition();
                    Vector3 forward = GetForward();
                    Vector3 up = GetUp();

                    //Set the original position
                    AkSoundEngine.SetObjectPosition(
                        Player,
                        position.x, position.y, position.z,
                        forward.x, forward.y, forward.z,
                        up.x, up.y, up.z);
                }
            }

            if (isEnvironmentAware && m_Collider)
            {
                m_envData = new AkGameObjEnvironmentData();
                //Check if this object is also an environment.
                m_envData.AddAkEnvironment(m_Collider, m_Collider);
            }
        }
        
        /// <summary>
        /// 声音的播放者。当需要更新位置时，是自己的Player，否则是Listener的Player
        /// </summary>
        public GameObject Player
        {
            get
            {
                if(IsUpdatePosition)
                {
                    return this.gameObject;
                }
                else
                {
                    return AudioManager.Instance.GlobalSoundObject;
                }
            }
        }

        public void OnDestroy()
        {
            if (StopOnDestroy)
            {
                if (AkSoundEngine.IsInitialized())
                    AkSoundEngine.StopAll(Player);
            }
            if (IsUpdatePosition)
            {
                if (AkSoundEngine.IsInitialized())
                    AkSoundEngine.UnregisterGameObj(Player);
            }
        }

        public void UpdatePosition()
        {
            if (IsUpdatePosition && m_posData != null)
            {
                // Get position with offset
                Vector3 position = GetPosition();
                Vector3 forward = GetForward();
                Vector3 up = GetUp();

                //Didn't move.  Do nothing.
                if (m_posData.position == position && m_posData.forward == forward && m_posData.up == up)
                    return;

                m_posData.position = position;
                m_posData.forward = forward;
                m_posData.up = up;

                //Update position
                AkSoundEngine.SetObjectPosition(
                    Player,
                    position.x, position.y, position.z,
                    forward.x, forward.y, forward.z,
                    up.x, up.y, up.z);
            }
        }

        public void Update()
        {
#if UNITY_EDITOR
            if (!UnityEditor.EditorApplication.isPlaying)
                return;
#endif
            if (isEnvironmentAware && m_envData != null)
                m_envData.UpdateAuxSend(gameObject, transform.position);

            UpdatePosition();
        }

        /// Gets the position including the position offset, if applyPositionOffset is enabled.
        /// \return  The position.
        public Vector3 GetPosition()
        {
            return transform.position;
        }        

        public virtual Vector3 GetForward()
        {
            return transform.forward;
        }

        public virtual Vector3 GetUp()
        {
            return transform.up;
        }

        void OnTriggerEnter(Collider other)
        {
            if (isEnvironmentAware && m_envData != null)
                m_envData.AddAkEnvironment(other, m_Collider);
        }

        void OnTriggerExit(Collider other)
        {
            if (isEnvironmentAware && m_envData != null)
                m_envData.RemoveAkEnvironment(other, m_Collider);
        }

#if UNITY_EDITOR
        public void OnDrawGizmosSelected()
        {
            Vector3 position = GetPosition();
            Gizmos.DrawIcon(position, "WwiseAudioSpeaker.png", false);
        }
#endif
        
    }
}
